#include "dom.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>	// atof

int DOM::load(const char * a_filename)
{
	FILE * pFile = 0;
	char buffer [1024];
	char data[100];
	int dataIndex = 0;
	char * name = 0;
	char * value = 0;
	char * emptyString = 0;
	char c;
	TemplateVector<DOM*> domStack;
	domStack.add(this);
	int levelsDeep = 0;

	fopen_s(&pFile, a_filename, "r");
	if (pFile == NULL)
	{
		perror ("Error opening file");
		return ERROR_FILE_OPEN;
	}
	else
	{
		while( ! feof (pFile) )
		{
			fgets (buffer , sizeof(buffer) , pFile);
			// if we just read the end of file, mark that we need to stop!
			if(feof (pFile))buffer[0] = -1;
			for(int i = 0; i < sizeof(buffer); ++i)
			{
				c = buffer[i];
				if(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == -1 || c == 0 || c == '{' || c == '}' || c == ';')
				{
					if(c == 0 || c == -1)
					{
						break;
					}
					else if(c == '{')
					{
						DOM * dom = new DOM();
						domStack.getLast()->m_subDom.add(name, dom);
						domStack.add(dom);
						for(int n = 0; n < levelsDeep; ++n)printf("   ");
						printf("%s {\n",name);
						name = 0;
						dataIndex = 0;
						levelsDeep++;
					}
					else if(c == '}')
					{
						domStack.pop();
						dataIndex = 0;
						levelsDeep--;
						for(int n = 0; n < levelsDeep; ++n)printf("   ");
						printf("}\n");
					}
					else if(c == ';')	// line comment
					{
						for(; i < sizeof(buffer) && buffer[i] != '\n'; ++i);
					}
					else if(dataIndex > 0)
					{
						// get the token
						value = new char[dataIndex+1];
						for(int a = 0; a < dataIndex; ++a)
						{
							value[a] = data[a];
						}
						value[dataIndex] = 0;
						// name part goes first
						if(!name)
						{
							name = value;
							if(c == '\n')	// if it ended in a new line
							{
								value = s_emptyString;	// empty string for value
							}
							else
							{
								value = 0;
							}
						}
						if(name && value)	// if both a name and value are known
						{
							for(int n = 0; n < levelsDeep; ++n)printf("   ");
							printf("%d %s %s\n", domStack.getLast()->getVarCount(), name, value);
							domStack.getLast()->add(name, value);	// add the pair
							name = 0;
							value = 0;
						}
						dataIndex = 0;
					}
				}
				else
				{
					data[dataIndex++] = c;
				}
			}
		}
		fclose (pFile);
		for(int i = 0; i < m_values.size(); ++i)
		{
			printf("%d %s %s\n",i, m_values.getKey(i), m_values.get(i));
		}
		printf("---\n");
		for(int i = 0; i < m_subDom.size(); ++i)
		{
			printf("%d %s %d (%d)\n",i, 
				m_subDom.getKey(i), m_subDom.get(i)->getVarCount(), m_subDom.get(i)->getSubCount());
		}
		printf("---\n");
	}
	return ERROR_NONE;
}
DOM::DOM(const char * a_filename)
{
	load(a_filename);
}
char * DOM::getString(char * varName)
{
	char ** r = m_values.getByKey(varName);
	if(!r)return 0;
	return *r;
}
float DOM::getFloat(char * varName)
{
	char * s = getString(varName);
	if(!s)return 0;
	return (float)atof(s);
}
int DOM::getInteger(char * varName)
{
	char * s = getString(varName);
	if(!s)return 0;
	if(s[0] == '0' && s[1] == 'x')
	{
		return (int)strtol(s+2, 0, 16);
	}
	return atoi(s);
}
bool DOM::isValueEqualTo(char * varname, char * value)
{
	char * s = getString(varname);
	if(!s)return false;
	return strcmp(s, value) == 0;
}

char * DOM::s_emptyString = "";
